//------------------------------------------------------------------------------
// <copyright file="RpcArchiveImplFactory.h" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#pragma once

#ifdef ENABLE_GAMESTEST_RPC

#include "RpcMemory.h"
#include <stack>
#include <mutex>

namespace Microsoft { namespace Internal { namespace GamesTest { namespace Rpc { namespace Server
{
	/// <summary> 
	/// An implementation of the RpcArchive class.
	/// </summary>
	class RpcArchiveImplFactory
	{
	private:
		/// <summary> 
		/// Shorthand definition for a pool of internal archive implementations.
		/// </summary>
		typedef std::stack<RpcArchiveImpl*> ImplementationFreeList;

		/// <summary> 
		/// Number of internal archive implementations to keep in the pool.
		/// </summary>
		static const int CACHE_SIZE;

	private:
		/// <summary> 
		/// Mutex used to lock resource pool when changing it.
		/// </summary>
		static std::mutex g_implementationLock;

		/// <summary> 
		/// The resource pool.
		/// </summary>
		static ImplementationFreeList g_freeList;

		/// <summary> 
		/// Releases a previously allocated archive implementation into the pool or destroys if the pool is full.
		/// </summary>
		/// <param name="pImpl">The previously allocated internal implementation to relase.</param>
		static void Release(RpcArchiveImpl* pImpl);

	public:
		/// <summary> 
		/// Returns an unused archive implementation from the pool or allocates a new one.
		/// </summary>
		/// <returns>A pointer to usable archive implementation.</returns>
		static RpcArchiveImplPtr Allocate();

		/// <summary> 
		/// Returns an unused archive implementation from the pool or allocates a new one, then deserializes from Json.
		/// </summary>
		/// <param name="json">Json node to deserialize from.</param>
		/// <returns>A pointer to usable archive implementation.</returns>
		static RpcArchiveImplPtr Deserialize(const JsonNode& json);

		/// <summary> 
		/// Returns an empty smart pointer used in scenarios where initial construction doesn't need to allocate an archive.
		/// </summary>
		/// <returns>A pointer to null archive implementation.</returns>
		inline static RpcArchiveImplPtr EmptyPointer()
		{
			return RpcArchiveImplPtr(nullptr, Release);
		}
	};

}}}}}

#endif // ENABLE_GAMESTEST_RPC